/**
 * 项目名：	Rumba Plan
 * 
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2007，所有权利保留。
 * 
 * 文件名：	RumbaLogger.java
 * 模块说明：	
 * 修改历史：
 * 2007-4-11 - lxm - 创建。
 */
package com.hd123.rumba.log;

import java.util.Enumeration;

import org.apache.log4j.Appender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority;
import org.apache.log4j.spi.AppenderAttachable;

import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.runtime.backprocess.BackProcess;
import com.hd123.rumba.user.IUser;

/**
 * 提供系统日志功能调用者，用于在大部分情况下替代{@link org.apache.log4j.Logger Logger}使用。
 * <p>
 * 
 * 这是一个Wrapper。对Logger进行了扩展：<br>
 * <li>在大部分情况下其功能与Logger相同。</li>
 * <li>若当前线程为BackProcess时，会以固定格式化的方式在message中加入process的相关信息。这样设计的目的在于通过{@link 
 * ProcessDBAppender}将日志信息写入数据库。</li>
 * 
 * @author lxm
 * 
 */
public class RumbaLogger implements AppenderAttachable {

  private Logger logger;
  private IUser operator = null;
  
  protected RumbaLogger() {
    // Do Nothing
  }

  public RumbaLogger(String name) {
    this.logger = Logger.getLogger(name);
  }

  public RumbaLogger(Class clazz) {
    this.logger = Logger.getLogger(clazz);
  }

  public static RumbaLogger getLogger(String name) {
    return new RumbaLogger(name);
  }

  public static RumbaLogger getLogger(Class clazz) {
    return new RumbaLogger(clazz);
  }
  
  public static RumbaLogger getRootLogger() {
    RumbaLogger logger = new RumbaLogger();
    logger.logger = Logger.getRootLogger();
    return logger;
  }

  public IUser getOperator() {
    return this.operator;
  }

  public void setOperator(IUser operator) {
    this.operator = operator;
  }

  public void addAppender(Appender arg0) {
    this.logger.addAppender(arg0);
  }

  public Enumeration getAllAppenders() {
    return this.logger.getAllAppenders();
  }

  public Appender getAppender(String arg0) {
    return this.logger.getAppender(arg0);
  }

  public boolean isAttached(Appender arg0) {
    return this.logger.isAttached(arg0);
  }

  public void removeAllAppenders() {
    this.logger.removeAllAppenders();
  }

  public void removeAppender(Appender arg0) {
    this.logger.removeAppender(arg0);
  }

  public void removeAppender(String arg0) {
    this.logger.removeAppender(arg0);
  }

  public void log(Priority level, Object message, Throwable t) {
    this.logger.log(RumbaLogger.class.getName(), level, encodeMessage(message), t);
  }

  public void log(Priority level, Object message) {
    // if (message instanceof Throwable)
    // this.log(level, decorateMessage(""), (Throwable) message);
    // else
    this.log(level, encodeMessage(message), null);
  }

  public void debug(Object message) {
    this.log(Level.DEBUG, message);
  }

  public void debug(Object message, Throwable t) {
    this.log(Level.DEBUG, message, t);
  }

  public void error(Object message) {
    this.log(Level.ERROR, message);
  }

  public void error(Object message, Throwable t) {
    this.log(Level.ERROR, message, t);
  }

  public void fatal(Object message) {
    this.log(Level.FATAL, message);
  }

  public void fatal(Object message, Throwable t) {
    this.log(Level.FATAL, message, t);
  }

  public void info(Object message) {
    this.log(Level.INFO, message);
  }

  public void info(Object message, Throwable t) {
    this.log(Level.INFO, message, t);
  }

  public void warn(Object message) {
    this.log(Level.WARN, message);
  }

  public void warn(Object message, Throwable t) {
    this.log(Level.WARN, message, t);
  }

  private Object encodeMessage(Object message) {
    Thread thread = Thread.currentThread();
    if (thread == null || !(thread instanceof BackProcess))
      return message;
    BackProcess process = (BackProcess) thread;

    try {
      StringBuffer sb = new StringBuffer();
      sb.append(ProcessDBAppender.PREFIX_MESSAGE); // 写入标记，以便ProcessDBAppender识别。
      appendProp(sb, ProcessDBAppender.KEY_DOMAIN_UUID, process.getDomain().getUuid());
      appendProp(sb, ProcessDBAppender.KEY_PROCESS_CLASSNAME, process.getClass().getName());
      appendProp(sb, ProcessDBAppender.KEY_PROCESS_UUID, process.getUuid());
      appendProp(sb, ProcessDBAppender.KEY_PROCESS_CAPTION, process.getCaption());
      String[] ownerKeys = process.getOwnerKeys();
      if (ownerKeys.length > 0 && ownerKeys[0] != null)
        appendProp(sb, ProcessDBAppender.KEY_OWNERKEY_1, ownerKeys[0]);
      if (ownerKeys.length > 1 && ownerKeys[1] != null)
        appendProp(sb, ProcessDBAppender.KEY_OWNERKEY_2, ownerKeys[1]);
      if (ownerKeys.length > 2 && ownerKeys[2] != null)
        appendProp(sb, ProcessDBAppender.KEY_OWNERKEY_3, ownerKeys[2]);
      if (ownerKeys.length > 3 && ownerKeys[3] != null)
        appendProp(sb, ProcessDBAppender.KEY_OWNERKEY_4, ownerKeys[3]);
      appendProp(sb, ProcessDBAppender.KEY_STARTTIME, (new Long(process.getStartTime().getTime()))
          .toString());
      if (operator != null)
        appendProp(sb, ProcessDBAppender.KEY_OPERATOR, operator.getNameCode());
      appendProp(sb, ProcessDBAppender.KEY_MESSAGE, message.toString());
      return sb.toString();
    } catch (BusinessException e) {
      return message;
    }
  }

  private void appendProp(StringBuffer sb, String caption, String value) {
    if (value == null)
      return;
    if (sb.length() > 0)
      sb.append("#");
    sb.append(caption);
    sb.append("=");
    sb.append(value);
  }
}
